#ifndef MATRIX_H
#define MATRIX_H

#include <math.h>
#include <iostream>
using namespace std;

template<typename T>
class Matrix
{
public:
	// Constructors
	Matrix();
	Matrix(int row, int col);
	Matrix(const Matrix<T> &m);

	// Destructor
	~Matrix();

	// Subscript operator
	T& operator () (int row, int col);

	// Assignment operator
	const Matrix<T>& operator = (const Matrix<T> &m);


	// Calculation operators
	Matrix<T> operator + (const Matrix<T> &m);
	Matrix<T> operator - (const Matrix<T> &m);
	Matrix<T> operator * (const Matrix<T> &m);
	Matrix<T> operator * (const T &num);
	friend Matrix<T> operator * (const T &num, const Matrix<T> &m){return (m*num);}
	Matrix<T> operator / (const T &num);

	// IO-stream operators
	template<typename U>
	friend istream & operator >>  (istream & input, const Matrix<U> &m);
	template<typename U>
	friend ostream & operator <<  (ostream & output, const Matrix<U> &m);
        int getRowSize() {return 0;}
        int getColSize() {return 0;}

	//We implement Logic operators for you. Do not change them
        // Logical operator
        bool operator == (const Matrix<T> &m);
        bool operator != (const Matrix<T> &m);

private:
        T **element;
        int _rowSize, _colSize;


};

template<typename T>
bool Matrix<T>::operator == (const Matrix<T> &m)
{
        if (_rowSize != m._rowSize || _colSize != m._colSize)
                return false;

        for (int i=0; i<_rowSize; i++)
                for (int j=0; j<_colSize; j++)
                        if (element[i][j] != m.element[i][j])
                                return false;

        return true;
}

// Logical operator: not euqal to
template<typename T>
bool Matrix<T>::operator != (const Matrix<T> &m)
{
        return (*this == m) ? false : true;
}


// Input stream function
template<typename T>
istream & operator >> (istream & input, const Matrix<T> & m)
{
   //To implement
   return input;
}

// Output stream function
template<typename T>
ostream & operator << (ostream & output, const Matrix<T> & m)
{
       //To implement

	return output;
}

template<typename T>
Matrix<T>::Matrix()
{
       //To implement

}

// Constructor
template<typename T>
Matrix<T>::Matrix(int row, int col)
{
       //To implement
}
// Copy constructor
template<typename T>
Matrix<T>::Matrix(const Matrix<T> &m)
{
       //To implement
}

// Destructor
template<typename T>
Matrix<T>::~Matrix()
{
       //To implement
}


// Subscript operator
template<typename T>
T& Matrix<T>::operator ()(int row, int col)
{
       //To implement

}

// Assignment operator
template<typename T>
const Matrix<T>& Matrix<T>::operator =(const Matrix<T> &m)
{
       //To implement

}


// Binary addition operator
template<typename T>
Matrix<T> Matrix<T>::operator +(const Matrix<T> &m)
{
       //To implement

	Matrix<T> result;
	return result;
}

// Binary subtraction operator
template<typename T>
Matrix<T> Matrix<T>::operator -(const Matrix<T> &m)
{
       //To implement

	Matrix<T> result;
	return result;
}

// Binary scalar multiplication operator
template<typename T>
Matrix<T> Matrix<T>::operator *(const T &num)
{
       //To implement

	Matrix<T> result;

	return result;
}

// Binary Matrix multiplication operator
template<typename T>
Matrix<T> Matrix<T>::operator *(const Matrix<T> &m)
{
       //To implement

	Matrix<T> result;

	return result;
}

// Binary division operator
template<typename T>
Matrix<T> Matrix<T>::operator /(const T &num)
{
       //To implement

	Matrix<T> result;
	return result;
}


#endif
